----------------------------------------------------------------------------------
-- Company: 
-- Engineer: Morten FAB
-- 
-- Create Date:	   15:07:29 04/07/2009 
-- Design Name: 
-- Module Name:	   ALU - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_SIGNED.all;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity ALU is
  generic(N : integer := 32);
  port (F0_IN	       : in  std_logic;
	 F1_IN	       : in  std_logic;
	 ENA_IN	       : in  std_logic;
	 ENB_IN	       : in  std_logic;
	 INVA_IN       : in  std_logic;
	 INC_IN	       : in  std_logic;
	 SLL8_IN       : in  std_logic;
	 SRA1_IN       : in  std_logic;
	 BusData_A_IN  : in  std_logic_vector (N-1 downto 0);
	 BusData_B_IN  : in  std_logic_vector (N-1 downto 0);
	 BusData_C_OUT : out std_logic_vector (N-1 downto 0);
	 SIGN_OUT      : out std_logic;
	 ZERO_OUT      : out std_logic;
	 CARRY_OUT     : out std_logic
	 );
end ALU;

architecture Behavioral of ALU is

  signal alu_control : std_logic_vector(5 downto 0); 
--alias ALUop:	     std_logic_vector( 5 downto 0) is MIR(21 downto 16);

begin
  alu_control <= F0_IN & F1_IN & ENA_IN & ENB_IN & INVA_IN & INC_IN;
  process(BusData_A_IN, BusData_B_IN, alu_control, SRA1_IN, SLL8_IN)
    variable temp      : std_logic_vector(N downto 0);
    variable extraTemp : std_logic_vector(N downto 0);
  begin
    
    case alu_control is
      when "011000" =>	---------------------------- Function: A
	temp := sxt(BusData_A_IN, N+1);
      when "010100" =>			--------------------------- Function: B
	temp := sxt(BusData_B_IN, N+1);
      when "011010" =>	--------------------------- Function: /A
	temp := sxt(not BusData_A_IN, N+1);
      when "101100" =>	---------------------------- Function: /B		
	temp := sxt(not BusData_B_IN, N+1);
      when "111100" =>	----------------------------- Function: A + B
	temp := sxt(BusData_A_IN, N+1) + sxt(BusData_B_IN, N+1);
      when "111101" =>	----------------------------- Function: A + B + 1
	temp := sxt(BusData_A_IN, N+1) + sxt(BusData_B_IN, N+1) + 1;
      when "111001" =>	------------------------------ Function: A + 1
	temp := sxt(BusData_A_IN + 1, N+1);
      when "110101" =>	------------------------------- Function: B + 1
	temp := sxt(BusData_B_IN + 1, N+1);
      when "111111" =>	-------------------------------- Function: B - A
	temp := sxt(BusData_B_IN, N+1) - sxt(BusData_A_IN , N+1);
      when "110110" =>	-------------------------------- Function: B - 1
	temp := sxt(BusData_B_IN, N+1)- 1;
      when "111011" =>	--------------------------------- Function: -A
	temp := sxt(-BusData_A_IN, N+1);
      when "001100" =>	--------------------------------- Function: A AND B
	temp := sxt(BusData_A_IN and BusData_B_IN , N+1);
      when "011100" =>	---------------------------------- Function: A OR B
	temp := sxt(BusData_A_IN or BusData_B_IN , N+1);
      when "010000" =>	---------------------------------- Function: 0
	temp := conv_std_logic_vector(0, temp'length);
      when "110001" =>	----------------------------------- Function: 1
	temp := conv_std_logic_vector(1, temp'length);
      when "110010" =>	----------------------------------- Function: -1
	temp := conv_std_logic_vector(-1, temp'length);
      when others =>
	temp := conv_std_logic_vector(0, temp'length);
    end case;

    CARRY_OUT <= temp(N-1);		--Carry detect
    SIGN_OUT  <= temp(N);		--Sign detect

    if temp = 0 then
      ZERO_OUT <= '1';
    else
      ZERO_OUT <= '0';
    end if;

    if SLL8_IN = '1' and SRA1_IN = '0' then
      temp := '0' & temp(N-9 downto 0) & "00000000";
    elsif SLL8_IN = '0' and SRA1_IN = '1' then
      temp := '1' & temp(N-1) & temp(N-1 downto 1);
    end if;

    BusData_C_OUT <= temp(N-1 downto 0);
  end process;

end Behavioral;

